#include <iostream>
#include <memory>
#include <string>

class Fruit
{
public:
    virtual void name() = 0;
};

class Apple : public Fruit
{
public:
    void name() override
    {
        std::cout << "我是一个苹果!" << std::endl;
    }
};

class Banana : public Fruit
{
public:
    void name() override
    {
        std::cout << "我是一个香蕉！" << std::endl;
    }
};

class Animal
{
public:
    virtual void name() = 0;
};

class Lamp : public Animal
{
public:
    void name() override
    {
        std::cout << "我是一只山羊！" << std::endl;
    }
};

class Dog : public Animal
{
public:
    void name() override
    {
        std::cout << "我是一只土狗！" << std::endl;
    }
};

// 简单工厂模式
// class FruitFactory
// {
// public:
//     static std::shared_ptr<Fruit> creat(const std::string &name)
//     {
//         if (name == "苹果")
//         {
//             return std::make_shared<Apple>();
//         }
//         else
//         {
//             return std::make_shared<Banana>();
//         }
//     }
// };

// 工厂方法模式
// class FruitFactory
// {
// public:
//     virtual std::shared_ptr<Fruit> creat() = 0;
// };

// class AppleFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> creat() override
//     {
//         return std::make_shared<Apple>();
//     }
// };

// class BananaFactory : public FruitFactory
// {
// public:
//     std::shared_ptr<Fruit> creat() override
//     {
//         return std::make_shared<Banana>();
//     }
// };

// 抽象工厂模式
class Factory
{
public:
    virtual std::shared_ptr<Fruit> creatFruit(const std::string &name) = 0;
    virtual std::shared_ptr<Animal> creatAnimal(const std::string &name) = 0;
};

class FruitFactory : public Factory
{
public:
    std::shared_ptr<Fruit> creatFruit(const std::string &name) override
    {
        if (name == "苹果")
        {
            return std::make_shared<Apple>();
        }
        else
        {
            return std::make_shared<Banana>();
        }
    }
    std::shared_ptr<Animal> creatAnimal(const std::string &name)
    {
        return std::shared_ptr<Animal>();
    }
};

class AnimalFactory : public Factory
{
public:
    std::shared_ptr<Fruit> creatFruit(const std::string &name) override
    {
        return std::shared_ptr<Fruit>();
    }
    std::shared_ptr<Animal> creatAnimal(const std::string &name) override
    {
        if (name == "山羊")
        {
            return std::make_shared<Lamp>();
        }
        else
        {
            return std::make_shared<Dog>();
        }
    }
};

class FactoryProducer
{
public:
    static std::shared_ptr<Factory> creat(const std::string &name)
    {
        if (name == "水果工厂")
        {
            return std::make_shared<FruitFactory>();
        }
        else
        {
            return std::make_shared<AnimalFactory>();
        }
    }
};

int main()
{
    // std::shared_ptr<Fruit> f = FruitFactory::creat("苹果");
    // f->name();
    // f=FruitFactory::creat("香蕉");
    // f->name();

    // std::shared_ptr<FruitFactory> ff(new AppleFactory());
    // std::shared_ptr<Fruit> f = ff->creat();
    // f->name();
    // ff.reset(new BananaFactory());
    // f = ff->creat();
    // f->name();

    std::shared_ptr<Factory> ff = FactoryProducer::creat("水果工厂");
    std::shared_ptr<Fruit> f = ff->creatFruit("苹果");
    f->name();
    f = ff->creatFruit("香蕉");
    f->name();

    std::shared_ptr<Factory> ffa = FactoryProducer::creat("动物工厂");
    std::shared_ptr<Animal> fa = ffa->creatAnimal("山羊");
    fa->name();
    fa = ffa->creatAnimal("土狗");
    fa->name();

    return 0;
}